// RMSWaveClientSocket.h: interface for the CRMSWaveClientSocket class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_RMSWAVECLIENTSOCKET_H__C9731D32_4233_4CDC_87DB_033258D7BBFE__INCLUDED_)
#define AFX_RMSWAVECLIENTSOCKET_H__C9731D32_4233_4CDC_87DB_033258D7BBFE__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include "../Common/RMSThread.h"
#include "../RMSLib/clientinterface.h"
#include "../Lib/Mutex.h"
#include "../Lib/lock.h"
#include "../Lib/Network.h"


#define	PACKET_COUNT 255
#define	PACKET_SYNC  10
#define	PACKET_SIZE 42 // 4 + 1 + 4 + 33 
#define	WAVE_SIZE 160

#include "../Common/sfec.h"

void DisplayStats(CSimpleFEC* pFEC);

class CAudioDecoder;
class CWaveData: protected LockObject
{
private:
	int		m_nSize;
	BYTE*	m_pWaveData;
	DWORD	m_dwBufLen;
	bool	m_bFull;
	enum 
	{ initial_buf_size = 33 };
	int		m_nActiveBuffer;
public:
	CWaveData();
	~CWaveData();

	void SetPacket(
					BYTE bPacketNum,
					DWORD dwWaveSize, 
					BYTE* pData,
					DWORD dwWaveSizeToCopy);
	void ClearPacket();
	bool IsFull() const;

	long DecodePacket(CAudioDecoder* pDecoder, BYTE* pDst);
};


class CWaveSync
{
public:
	CEvent	m_eventSync;
	bool	m_bSync;

	CWaveData m_Audio[PACKET_COUNT];

//	CRITICAL_SECTION m_criticalAction;
	Mutex m_criticalAction;

	BYTE m_byPacketNumber;
	BYTE m_byPacketNumberStart;
	BYTE m_byPacketSync;

    volatile BYTE m_LastStored;

	CWaveSync()
	{
		m_bSync = false;
		m_byPacketNumber = 0;
		m_byPacketNumberStart = 0;
		m_byPacketSync = 0;
        m_LastStored = 0;
	}

	int	 Sync()
	{
		int result;
		m_criticalAction.Lock();
		result = m_byPacketNumberStart;
		m_bSync = true;
		m_criticalAction.Unlock();
		return result;	
	}

	virtual BOOL StartWaveSession(ClientInterface* pClient, const char *szServerIP, int nServerPort)
	{
		return TRUE;
	};
};


class CRMSWaveClientSocket : public CRMSThread, public ClientAccess, public CWaveSync, protected LockObject
{
public:
	CRMSWaveClientSocket();
	virtual ~CRMSWaveClientSocket();

	BOOL StartWaveSession(ClientInterface* pClient, const char *szServerIP, int nServerPort);

	enum STATE
	{
		STATE_STOP, STATE_EXIT, STATE_RUN, STATE_RESTART
	};

	const STATE& GetState();
	bool SetState(const STATE& rState);
    void setCallBack(CCallBack* pCB) {pCallBack = pCB;};

	DWORD OnTerminate();
	void OnCriticalTerminate();

protected:
	DWORD ThreadFunc();
private:

    CSimpleFEC* pFEC;
    CCallBack* pCallBack;

	STATE m_threadState;
	BOOL StopWaveSession();
	void WaitForStateChange(const STATE& rPrevState);
	void OnError(int err = 0);

	bool MakeThreadStep(int& nLen, BYTE*& pSrc, DWORD& dwTag);
#ifdef WIN32
	HANDLE m_hStateEvents[1]; // start + exit
#endif

	bool m_bActive;
	bool m_bSessionStarted;
    int prebuf;

	
	STREAMBOX_SOCKET m_UDPsocket;

#ifdef USE_OLD_SOCKET
	bool MyRecieveData(STREAMBOX_SOCKET* s,
					   char FAR* buf,
					   int len,
					   int flags,
					   struct sockaddr FAR *from,
					   int FAR *fromlen);
#else //def USE_OLD_SOCKET
	int initSocket(STREAMBOX_SOCKET* pSock/*, const char* szLocalIP*/, int nTCPPort = 777);
	int recievePacket(STREAMBOX_SOCKET *pSock, void *buf, int nBufSize);
	int setNonDelayMode(STREAMBOX_SOCKET *pSock);
#endif //def USE_OLD_SOCKET

	int closeSocket(STREAMBOX_SOCKET* pSock);

	bool ParseTags(DWORD& dwTag, BYTE*& pSrc,int Len);

    int nfiles;

	SOCKADDR_IN m_saServer;
	SOCKADDR_IN m_saClient;

	BYTE* m_pData;
	BYTE* m_pData2[2];
	int m_flip;

	void CloseSession();
};


#endif // !defined(AFX_RMSWAVECLIENTSOCKET_H__C9731D32_4233_4CDC_87DB_033258D7BBFE__INCLUDED_)
